import pandas as pd
import numpy as np
import pandas_datareader as web
import datetime
import plotly.express as px
Using the Yahoo API and pandas_datareader library to retrieve quotes for financial instruments (stock indices, stocks, etc.)
# Downloading Quotes from Yahoo
interval = 'mo'
symbol = '^GSPC'#'^IXIC'#'BCS'#'GE'#'^FCHI'#'^GSPC'
time = 'A'
start = datetime.datetime(1988,1,1) #"1988-01-01"
end = datetime.datetime(2022,5,31) #"2018-03-01"
df = web.get_data_yahoo(symbol, start = start, end = end, interval=interval)
# df1 = web.DataReader(name='AMZN', data_source='stooq')
# df1
f = df.copy()
# Definition of leverage level: 'leverage'
leverage = 3
# import plotly.graph_objects as go
# Get the 26-day EMA of the closing price
k = f['Close'].ewm(span=12, adjust=False, min_periods=12).mean()
# Get the 12-day EMA of the closing price
d = f['Close'].ewm(span=26, adjust=False, min_periods=26).mean()
# Subtract the 26-day EMA from the 12-Day EMA to get the MACD
macd = k - d
# Get the 9-Day EMA of the MACD for the Trigger line
macd_s = macd.ewm(span=12, adjust=False, min_periods=12).mean()
# Calculate the difference between the MACD - Trigger for the Convergence/Divergence value
macd_h = macd.ewm(span=5, adjust=False, min_periods=5).mean() - macd_s
# Add all of our new values for the MACD to the dataframe
f['macd'] = f.index.map(macd)
f['macd'] = f['macd'].ewm(span=5, adjust=False, min_periods=5).mean()
f['macd_h'] = f.index.map(macd_h)
f['macd_s'] = f.index.map(macd_s)
f = f.dropna()
# Definition of long and short trades
conditions = [
(f['macd_h'] >= 0),
(f['macd_h'] < 0)]
choices = [1, 0]
f['long/short'] = np.select(conditions, choices, default=0)
# Calculating the rate of return on a stock index
f['dc'] = (f['Close']/f['Close'].shift(1))-1
# Calculating the rate of return on long or short trades taking into account the financial leverage
f['profit'] = f['dc'] * f['long/short'].shift(1) * leverage
f = f.dropna()
# Determination of cumulative return from stock index and model
f['cumprofit'] = (1 + f['profit']).cumprod()
f['cumclose'] = f['Close'][f.index[:]]/f['Close'][f.index[0]]
window = 252
# Calculate the max drawdown in the past window days for each day in the series.
# Use min_periods=1 if you want to let the first 252 days data have an expanding window
Roll_Max = f['cumprofit'].rolling(window, min_periods=1).max()
f['DD'] = f['cumprofit']/Roll_Max - 1.0
# Next we calculate the minimum (negative) daily drawdown in that window.
# Again, use min_periods=1 if you want to allow the expanding window
Max_Daily_Drawdown = f['DD'].rolling(window, min_periods=1).min()
# Determining the period for calculating CAGR
f['dat'] = f.index
diff = f['dat'][-1] - f['dat'][0]
timedelta = pd.Timedelta(diff)
n = timedelta.days
print("Leverage: ", leverage)
print("Cumulative returns of Index: ", np.round(f['cumclose'].iloc[-1], 2))
print("Cumulative returns of Model: ", np.round(f['cumprofit'].iloc[-1], 2))
# CAGR
print("CAGR (Index): ", str(np.round(f['cumclose'].iloc[-1]**((365/n))-1, 2)*100) + " %")
print("CAGR (Model): ", str(np.round(f['cumprofit'].iloc[-1]**((365/n))-1, 2)*100) + " %")
fig = px.line(
f,
x=f.index,
y='Close',
title = symbol + ' (' + interval + ')',
labels={
"Close": "Close",
"DateId": "Date",
},
width=900,
height=400
)
fig.update_layout(
margin=dict(t=50, b=20),
)
fig.update_xaxes(title=None)
fig.show()
#####################################################################################################
# The function changes the existing names in the legend taken from the column name to the new defined names
def custom_legend_name(new_names):
for i, new_name in enumerate(new_names):
fig.data[i].name = new_name
#####################################################################################################
fig = px.line(
f,
x=f.index,
y=['cumclose', 'cumprofit'],
#title = symbol + ' (' + interval + ')',
labels={
"value": "Capital",
"Date": "Data",
"variable": "Legend",
},
log_y=True,
width=900,
height=400
)
custom_legend_name(['Index Price','Model'])
fig.update_layout(legend=dict(
yanchor="top",
y=0.99,
xanchor="left",
x=0.01
))
fig.update_layout(
margin=dict(t=50, b=20),
)
fig.update_xaxes(title=None)
fig.show()
fig = px.line(
f,
x=f.index,
y=['macd', 'macd_s'],
labels={
"value": "MACD",
"Date": "Data",
"variable": "Legend",
},
width=900,
height=200
)
custom_legend_name(['MACD','MACD Signal'])
fig.update_layout(
margin=dict(t=20, b=20),
showlegend=False
)
fig.update_xaxes(title=None)
fig.show()
fig = px.line(
f,
x=f.index,
y='long/short',
#title = symbol + ' (' + interval + ')',
labels={
"kappa": "Kappa Value",
"Date": "Data",
"variable": "Legend",
},
width=900,
height=200
)
fig.update_xaxes(title=None)
fig.update_layout(
margin=dict(t=20, b=20)
)
fig.show()
fig = px.line(
f,
x=f.index,
y=f['DD'],
labels={
"value": "MACD",
"Date": "Data",
"variable": "Legend",
},
width=900,
height=200
)
#custom_legend_name(['MACD','MACD Signal'])
fig.update_layout(
margin=dict(t=20, b=20),
showlegend=False
)
fig.update_xaxes(title=None)
fig.show()
f.to_csv('macd.csv')
Leverage: 3 Cumulative returns of Index: 11.26 Cumulative returns of Model: 209.34 CAGR (Index): 8.0 % CAGR (Model): 19.0 %